/***********************************************/
//1. pms 
//import liberary https://github.com/i3water/Blinker_PMSX003ST
#include "BLINKER_PMSX003ST.h"

// CONNECTIONS:
// pms PIN1-Vcc --> Vcc - 3v3 - 5v
// pms PIN2-Gnd --> Gnd
// pms PIN4 --> 10
// pms LV1 --> HU1
// pms PIN5 --> 11
// pms LV2 --> HU2

#if defined(ESP32)
HardwareSerial pmsSerial(2);// UART1/Serial1 pins 16,17
#else
#include <SoftwareSerial.h>
SoftwareSerial pmsSerial(10,11);  //rxPin, txPin, mega 10，11，12，13，50，51，52，53，62，63，64，65，66，67，68，69
#endif

BLINKER_PMSX003ST pms;

/***********************************************/
//2.gas 
// http://lafudo.blogspot.com/2013/11/arduino-tgs2602.html
int gasSensor = 14; // 指定要量測的analog腳位為2
int gasval = 0;

/***********************************************/
//3.light sensor
#include <Wire.h>
// GY-30 BH1750FVI
// in ADDR 'L' mode 7bit addr
#define ADDR 0b0100011
// addr 'H' mode
// #define ADDR 0b1011100

/***********************************************/
// 4.rllight
int rlwaterpp = 8;  //water pump
int rllight = 9;  // led light 
int rlfan = 12; // fan
// char watersensor= "A5"; //water sensor port

/***********************************************/
// 5.DS1302 clock sesor
//import liberary Rtc by Makuna  https://github.com/Makuna/Rtc/wiki
// CONNECTIONS:
// DS1302 CLK/SCLK --> 5
// DS1302 DAT/IO --> 6
// DS1302 RST/CE --> 7
// DS1302 VCC --> 3.3v - 5v
// DS1302 GND --> GND
#include <ThreeWire.h>
#include <RtcDS1302.h>
ThreeWire myWire(/*IO*/6,/*SCLK*/5,/*CE*/7); // IO, SCLK, CE
RtcDS1302<ThreeWire> Rtc(myWire);

/***********************************************/

void inipms() {
    Serial.println("\nStart");
    pmsSerial.begin(9600);
    pms.begin(pmsSerial);
    //  pms.wakeUp();
    pms.setMode(PASSIVE);
}

void looppms () {
  pms.request();
  Serial.println( "/********************/" );
  Serial.println( "There are pms sensor val: " );
    Serial.println("request");
    if(!pms.read()){
      Serial.println("read failed");
        return;
    }
    Serial.print("PM1.0(CF1)\t");
    Serial.print(pms.getPmCf1(1.0));
    Serial.println("ug/m3");
    Serial.print("PM2.5(CF1)\t");
    Serial.print(pms.getPmCf1(2.5));
    Serial.println("ug/m3");
    Serial.print("PM10(CF1)\t");
    Serial.print(pms.getPmCf1(10));
    Serial.println("ug/m3");
    Serial.print("PM1.0(ATO)\t");
    Serial.print(pms.getPmAto(1.0));
    Serial.println("ug/m3");
    Serial.print("PM2.5(ATO)\t");
    Serial.print(pms.getPmAto(2.5));
    Serial.println("ug/m3");
    Serial.print("PM10(ATO)\t");
    Serial.print(pms.getPmAto(10));
    Serial.println("ug/m3");
    Serial.print("  PCS0.3\t");
    Serial.print(pms.getPcs(0.3));
    Serial.println("pcs/0.1L");
    Serial.print("  PCS0.5\t");
    Serial.print(pms.getPcs(0.5));
    Serial.println("pcs/0.1L");
    Serial.print("  PCS1.0\t");
    Serial.print(pms.getPcs(1));
    Serial.println("pcs/0.1L");
    Serial.print("  PCS2.5\t");
    Serial.print(pms.getPcs(2.5));
    Serial.println("pcs/0.1L");
    Serial.print("  PCS5.0\t");
    Serial.print(pms.getPcs(5));
    Serial.println("pcs/0.1L");
    Serial.print("   PCS10\t");
    Serial.print(pms.getPcs(10));
    Serial.println("pcs/0.1L");
    Serial.print("Formalde\t");
    Serial.print(pms.getForm());
    Serial.println("ug/m3");
    Serial.print("Temperat\t");
    Serial.print(pms.getTemp());
    Serial.println("'C");
    Serial.print("Humidity\t");
    Serial.print(pms.getHumi());
    Serial.println("%");
    Serial.println();
 //   delay(3000); 
}

void loopgas() {
  gasval = analogRead(gasSensor);
  Serial.println( "/********************/" );
  Serial.println( "There are gas sensor val:" );
  Serial.println( gasval );
//  delay(500);
}

void humidity() 
{
  int a_val = 0;
  a_val = analogRead(A2);
  Serial.println("/********************/" );
  Serial.print(a_val);
  Serial.println(".%HR");
  if(a_val > 450){
     openrelay(rlwaterpp,6000);
  } 
}

// open relay for msec micro second
void openrelay(int rldp,int msec){
  digitalWrite(rldp,LOW);
  delay(msec);
  digitalWrite(rldp,HIGH);
//  delay(msec);
      Serial.println("/********************/" );
      Serial.print("open relay: ");
      Serial.println(rldp);
}

void light()
{
  int val = 0;
  // reset
  Wire.beginTransmission(ADDR);
  Wire.write(0b00000111);
  Wire.endTransmission();
 
  Wire.beginTransmission(ADDR);
  Wire.write(0b00100000);
  Wire.endTransmission();
  // typical read delay 120ms
  delay(120);
  Wire.beginTransmission(ADDR);
  Wire.requestFrom(ADDR, 2); // 2byte every time
  Wire.endTransmission();
  for (val = 0; Wire.available() >= 1; ) {
    char c = Wire.read();
    Serial.println(c, HEX);
    val = (val << 8) + (c & 0xFF);
  }
  val = val / 1.2;
  if(val >= 5 && val <= 300){ 
    Serial.print("cloudy: ");
    openrelay(rllight,3000);    
    }
   else if(val >= 300){
     Serial.print("sunny: ");
    }
  Serial.print(val);
  Serial.println(".lx OK");
//  delay(100);
}

void watermark()
{
   double b, c;
   b = (long)analogRead(A6);
   c = (b / 650) * 4;
  Serial.print("The depth is:");
  Serial.print(c);
  Serial.println("cm.");
  delay(80);  
  if (c <= 1.3) {
    digitalWrite(3,HIGH);
    delay(500);
    digitalWrite(3,LOW);
    delay(500);
  }
}

#define countof(a) (sizeof(a) / sizeof(a[0]))
void printDateTime(const RtcDateTime& dt)
{
    char datestring[20];
    snprintf_P(datestring,
            countof(datestring),
            PSTR("%02u/%02u/%04u %02u:%02u:%02u"),
            dt.Month(),
            dt.Day(),
            dt.Year(),
            dt.Hour(),
            dt.Minute(),
            dt.Second() );
    Serial.print(datestring);
}

void openfan () {
/*  if (pms.getPmCf1(2.5) >= 75) {
    openrelay(rlfan,1);
  }else if(pms.getPmCf1(1.0) >= 150) {
    openrelay(rlfan,1);
  }else if(pms.getForm() >= 60) {
    openrelay(rlfan,1);
  }else if (gasval >= 160) {
    openrelay(rlfan,1);
  } */
  if((pms.getPmCf1(2.5) >= 75 || pms.getPmCf1(1.0) >= 150 || pms.getForm() >= 60 || gasval >= 160)) {
    openrelay(rlfan,10000);
  }
}

void setup() {
    // 1. Intial  light sensor:
  Serial.begin(9600);
  Wire.begin();
  Wire.beginTransmission(ADDR);
  Wire.write(0b00000001);
  Wire.endTransmission();

  // 2. Initial relay for waterpump and led light
  pinMode(rlwaterpp, OUTPUT);
  pinMode(rllight, OUTPUT);
  pinMode(rlfan,OUTPUT);
    
    digitalWrite(rlwaterpp,HIGH);
    digitalWrite(rllight,HIGH);
    digitalWrite(rlfan,HIGH);
   
  // 3. Inital Watermark Sensor
  pinMode(A5,INPUT);

  // 4.  Intial RTC
    Rtc.Begin();
    RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__);
    printDateTime(compiled);
    Serial.println();
    if (Rtc.GetIsWriteProtected())
    {
        Serial.println("RTC was write protected, enabling writing now");
        Rtc.SetIsWriteProtected(false);
    }
    if (!Rtc.GetIsRunning())
    {
        Serial.println("RTC was not actively running, starting now");
        Rtc.SetIsRunning(true);
    }
      Rtc.SetDateTime(compiled);
    RtcDateTime now = Rtc.GetDateTime();
    printDateTime(now);
    if (now < compiled)
    {
        Serial.println("RTC is older than compile time!  (Updating DateTime)");
        Rtc.SetDateTime(compiled);
    }
    else if (now > compiled)
        Serial.println("RTC is newer than compile time. (this is expected)");
    else if (now == compiled)
        Serial.println("RTC is the same as compile time! (not expected but all is fine)"); 
    inipms();
}

void loop() {
/*  int hour;
  RtcDateTime now = Rtc.GetDateTime();
  hour= now.Hour();
  Serial.println(hour);
  if (hour > 9 && hour < 24){ 
    Serial.print("hour: ");
      Serial.println(hour);   */  
  light();
    humidity();
    watermark();  
    looppms();
    loopgas();
    openfan();
    delay(10000);
 /* }
  else {   
    Serial.print("hour: ");
    Serial.println(hour);
    Serial.print("It's");
    Serial.print(hour);
    Serial.print("o'clock now. Let's start tomorrow");
    delay(3600);
  }  */

}      
